﻿namespace NTLib.Pipe.UTest.Targets
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using NTLib.Pipe.Targets;
    using NTLib.Core.Tasks;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Test.Resources;
    using Descriptors;
    [TestClass]
    public class TargetUTest : BaseTestClass
    {
        #region Methods

        [TestCategory("Pipe.Targets")]
        [TestMethod]
        public void TargetManager_RegisterUnRegister()
        {
            var timeout = base.CreateTimeout(15);
            using (base.LockTest(timeout.Token))
            {
                TargetManager.Instance.Clear();

                const string testA = "TestA";
                TestTargetProvider register = new TestTargetProvider(testA, typeof(string));

                TargetManager.Instance.Register(register);

                TargetManager.Instance.UnRegister(register);

                TargetManager.Instance.Register(register);
                TargetManager.Instance.UnRegister(register.Id);
            }
        }

        [TestCategory("Pipe.Targets")]
        [TestMethod]
        public void TargetManager_DefaultLocationTarget()
        {
            var timeout = base.CreateTimeout(15);
            using (base.LockTest(timeout.Token))
            {
                TargetManager.Instance.Clear();

                LocalTargetLocation local = new LocalTargetLocation();

                var desc = TargetManager.Instance.LocateAsync(local, timeout.Token).WaitResult(timeout.Token);

                Assert.AreEqual(desc.Count(), 1);
                Assert.AreEqual(desc.First(), LocalTargetDescription.Instance);
            }
        }

        [TestCategory("Pipe.Targets")]
        [TestMethod]
        public void TargetManager_RegisterMultipleUnRegister()
        {
            var timeout = base.CreateTimeout(15);
            using (base.LockTest(timeout.Token))
            {

                TargetManager.Instance.Clear();

                const string testA = "TestA";
                const string testB = "TestB";
                TestTargetProvider register = new TestTargetProvider(testA, typeof(string));
                TestTargetProvider registerB = new TestTargetProvider(testB, typeof(string), typeof(int));

                TargetManager.Instance.Register(register);
                TargetManager.Instance.Register(registerB);

                TargetManager.Instance.Register(register);
            }
        }

        [TestCategory("Pipe.Targets")]
        [TestMethod]
        public void TargetManager_Provide()
        {
            var timeout = base.CreateTimeout(15);
            using (base.LockTest(timeout.Token))
            {

                TargetManager.Instance.Clear();

                const string testA = "TestA";
                const string testB = "TestB";
                const string testmsg = "Test simple";

                TestTargetProvider register = new TestTargetProvider(testA, typeof(int));
                TestTargetProvider registerB = new TestTargetProvider(testB, typeof(string), typeof(int));

                TargetManager.Instance.Register(register);
                TargetManager.Instance.Register(registerB);

                var t = TargetManager.Instance.LocateAsync(testmsg);
                t.Wait();

                var data = t.Result.ToArray();

                Assert.IsNotNull(data);
                Assert.AreEqual(data.Length, 1);
                Assert.IsInstanceOfType(data[0], typeof(TestTargetDesciption<string>));

                var testTarget = (TestTargetDesciption<string>)data[0];

                Assert.AreEqual(testTarget.Signature, testB);
                Assert.AreEqual(testTarget.Value, testmsg);

                TargetManager.Instance.UnRegister(registerB.Id);

                var t2 = TargetManager.Instance.LocateAsync(testmsg);
                t2.Wait();

                data = t2.Result.ToArray();

                Assert.IsNotNull(data);
                Assert.AreEqual(data.Length, 0);
            }
        }

        [TestCategory("Pipe.Targets")]
        [TestMethod]
        public void TargetManager_ProviderMultiple()
        {
            var timeout = base.CreateTimeout(15);
            using (base.LockTest(timeout.Token))
            {

                TargetManager.Instance.Clear();
                const string testA = "TestA";
                const string testB = "TestB";
                const string testmsg = "Test simple";

                TestTargetProvider register = new TestTargetProvider(testA, typeof(string));
                TestTargetProvider registerB = new TestTargetProvider(testB, typeof(string), typeof(int));

                TargetManager.Instance.Register(register);
                TargetManager.Instance.Register(registerB);

                var t = TargetManager.Instance.LocateAsync(testmsg);
                t.Wait();

                var data = t.Result.ToArray();

                Assert.IsNotNull(data);
                Assert.AreEqual(data.Length, 2);
                Assert.IsInstanceOfType(data[0], typeof(TestTargetDesciption<string>));
                Assert.IsInstanceOfType(data[1], typeof(TestTargetDesciption<string>));

                var testTarget = (TestTargetDesciption<string>)data[0];
                var testTargetB = (TestTargetDesciption<string>)data[1];

                Assert.AreEqual(testTarget.Signature, testA);
                Assert.AreEqual(testTarget.Value, testmsg);

                Assert.AreEqual(testTargetB.Signature, testB);
                Assert.AreEqual(testTargetB.Value, testmsg);

                TargetManager.Instance.UnRegister(register);
                var t2 = TargetManager.Instance.LocateAsync(testmsg);
                t2.Wait();

                data = t2.Result.ToArray();
                Assert.IsNotNull(data);
                Assert.AreEqual(data.Length, 1);

                TargetManager.Instance.UnRegister(registerB);

                var t3 = TargetManager.Instance.LocateAsync(testmsg);
                t3.Wait();

                data = t3.Result.ToArray();
                Assert.IsNotNull(data);
                Assert.AreEqual(data.Length, 0);
            }
        }
        #endregion
    }
}
